fix(cli): five deploy roll-up fixes from the #2957 wave-4 checklist#3169
Merged
Conversation
- DEP-11a: same-version redeploy — force-remove a conflicting same-name
container before docker run (exact-anchored name filter, xargs -r
idempotent) and stop superseded versions best-effort after the
kamal-proxy cutover (AppCommands.remove_conflicting / stop_old_versions,
wired into DeployMainCli.$deploy).
- DEP-11b: 'wheels deploy secrets extract' key match is now exact —
CFML == is case-insensitive, so 'extract path' matched the PATH line.
- DEP-11c: kamal-proxy config volume derives the remote home from the
ssh user (/root for the default root user) instead of hardcoding
/home/<user>.
- SecretResolver: bounded stdout drain + deadline (default 60s,
opts.timeoutSeconds) replaces the unbounded waitFor()/read-to-EOF —
an interactively-blocking secrets command now kills bash and throws
SecretResolver.ResolutionFailed with a clear message.
- rollback() forwards {destination} into ConfigLoader.load — it was the
last verb not applying the --destination overlay (same class as 3085).
All five red-first specs plus full CLI suite green in the lucee7 docker
harness (1015 pass / 0 fail; 2 known docker-env artifacts).
Refs #2957
Signed-off-by: Peter Amiri <peter@alurium.com>
added 2 commits
June 12, 2026 21:51
Signed-off-by: Peter Amiri <petera@pai.com>
Signed-off-by: Peter Amiri <petera@pai.com> # Conflicts: # cli/lucli/services/deploy/cli/DeployMainCli.cfc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Wave 4 ("roll-up point fixes") of the #2957 deploy-orchestration campaign — five independent point fixes, each red-first TDD'd against
FakeSshPool/ dry-run flows.Ticks these Wave 4 checklist items from #2957's 2026-06-12 re-scope:
Plus one item listed under Wave 2 in the issue but assigned to this wave by the campaign plan:
Changes
AppCommands.remove_conflicting()(docker container ls --all --filter name=^<name>$ --quiet | xargs -r docker container rm --force) dispatched before each apprun;AppCommands.stop_old_versions()(label-scopeddocker psexcluding the current name,xargs -r docker stop) dispatched best-effort (allowFail=true) after the kamal-proxy cutover so a failed stop of an OLD container can't fail the NEW deploy.DeploySecretsCli.extract()usescompare(left(line, eq - 1), key) == 0— exact match like Kamal; previouslyextract pathreturned thePATHvalue.ProxyCommands.$remoteHome():/rootfor the defaultrootssh user,/home/<user>otherwise; the config volume mount uses it.$runBashtimeoutSecretResolverdrains stdout via a deadline-boundedavailable()poll (covers both hang shapes: silent never-exits AND endless streamers),destroyForcibly()on expiry, throwsSecretResolver.ResolutionFailedwith an actionable message. Default 60s, configurable via initopts.timeoutSeconds. Replaces the unbounded read-to-EOF +waitFor().--destinationrollback()forwards{destination: opts.destination ?: ""}intoConfigLoader.load()— the last verb not applying the overlay (same defect class as theconfig()fix in #3085).Testing
Red-first per item, then full CLI suite in the lucee7 docker harness (
/wheels/cli/tests?format=json):DeploySecretsCliSpec1 fail,ProxyCommandsSpec1 fail,AppCommandsSpec2 errors,DeployMainCliSpec3 fail + 1 error,SecretResolverSpec1 fail.SshClientSpec/SshPoolSpecdocker-not-found), matching the campaign baseline tolerance.< 10sfor asleep 30secrets command withtimeoutSeconds: 1).Real SSH / remote-docker behavior is unverifiable in this harness —
FakeSshPoolspecs and--dry-runflows are the verification bar here, per campaign convention. The env-gatedE2EDeploySpec(DEPLOY_E2E=1) remains the live-SSH follow-up surface.Refs #2957
🤖 Generated with Claude Code